home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Merciful 2
/
Merciful - Disc 2.iso
/
software
/
d
/
devioustools25.dms
/
devioustools25.adf
/
utils
/
015.lzx
/
MountDos.e
< prev
next >
Wrap
Text File
|
1981-01-30
|
13KB
|
489 lines
OPT REG=5
OPT PREPROCESS
OPT OSVERSION=37
/*
* MS-Dos partitiontable lister and Cross-Dos mounter for PC-HD's.
*
* (c) K.P. van Beem (patrick@aobh.xs4all.nl or 2:280/464.2)
*
* Based on information gained from the source of the Linux FDisk, by
* A. V. Le Blanc (LeBlanc@mcc.ac.uk).
* This program is free software. You can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* Version 1.0, 28-1-96, Initial version.
*/
#define VERSION '$VER: MountDos 1.0 (28.1.96) PD, (c) K.P. van Beem.\n'
MODULE 'devices/trackdisk', 'exec/io', 'exec/ports'
MODULE 'dos/dos', 'dos/dostags'
MODULE 'utility/tagitem'
MODULE 'icon', 'workbench/workbench', 'workbench/startup'
/******************* Globals **********************/
#define TEMPLATE 'DEVICE,UNIT/N,LIST/S,GENERATE/S,MOUNT/S,QUIET/S'
#define ARG_DEVICE arg_ptrs[0]
#define ARG_UNIT arg_ptrs[1]
#define ARG_LIST arg_ptrs[2]
#define ARG_GENERATE arg_ptrs[3]
#define ARG_MOUNT arg_ptrs[4]
#define ARG_QUIET arg_ptrs[5]
#define NUMARGS 6
#define TMPFILENAME 'T:MountDosTmpMountlist'
#define EXTENDED 5
#define SECTOR_SIZE 512
#define PART_TABLE_FLAG $55AA
-> Actually $AA55, but ix86's are realy weird. They swap multiple-byte values.
-> Byte values. Highest two bits of sector are added to cylinder.
#define SECTOR(s) (s AND $3F)
#define CYLINDER(s,c) (c OR Shl(s AND $C0,2))
-> This is how an MS-Dos partition entry looks like:
OBJECT partition
boot_ind :CHAR -> 0x80 - active
head :CHAR -> starting head
sector :CHAR -> starting sector
cyl :CHAR -> starting cylinder
sys_ind :CHAR -> What partition type
end_head :CHAR -> end head
end_sector :CHAR -> end sector
end_cyl :CHAR -> end cylinder
start_sect :LONG -> starting sector counting from 0
nr_sects :LONG -> nr of sectors in partition
ENDOBJECT
-> Global return-code
DEF rc = RETURN_OK -> Exceptionhandler will correct this.
-> Program arguments
DEF rargs = NIL
DEF arg_ptrs = NIL : PTR TO LONG
DEF device, unit -> Device and unit we work on
-> Device handling
DEF tio = NIL :PTR TO ioexttd -> Trackdisk io blok.
-> Count number of partitions found, for unique naming of mount-entries
DEF dosparts, ndosparts
/****************** Automatic exceptions **********************/
-> What can go wrong...
RAISE "CTLC" IF CtrlC() = TRUE,
"DEV" IF OpenDevice() <> NIL,
"DOS" IF ReadArgs() = NIL,
"IO" IF DoIO() <> NIL,
"LIB" IF OpenLibrary() = NIL,
"RES" IF CreateIORequest() = NIL,
"RES" IF CreateMsgPort() = NIL,
"STAC" IF FreeStack() < 1000
/****************** Main prog **********************/
PROC main() HANDLE
-> Device handling
DEF tmp = NIL -> MsgPort for the trackdisk.device
DEF topen = FALSE -> Flag if the trackdisk.device is opened.
-> WB args
DEF arg :PTR TO wbarg, dobj :PTR TO diskobject, wm :PTR TO wbstartup
DEF olddir, item
-> Check the parameters we got, first, initial and default values.
NEW arg_ptrs[NUMARGS]
device := 'scsi.device'
IF wbmessage
-> Started from workbench
iconbase := OpenLibrary('icon.library', 0)
wm := wbmessage
arg := wm.arglist
IF wm.numargs > 1 THEN arg++ -> We are called with a project.
olddir := CurrentDir(arg.lock)
dobj := GetDiskObject(arg.name)
IF dobj
IF FindToolType(dobj.tooltypes,'LIST') THEN ARG_LIST := TRUE
IF FindToolType(dobj.tooltypes,'GENERATE') THEN ARG_GENERATE := TRUE
IF FindToolType(dobj.tooltypes,'MOUNT') THEN ARG_MOUNT := TRUE
IF FindToolType(dobj.tooltypes,'QUIET') THEN ARG_QUIET := TRUE
item := FindToolType(dobj.tooltypes,'DEVICE')
IF item
device := String(StrLen(item))
StrCopy(device, item)
ENDIF
item := FindToolType(dobj.tooltypes,'UNIT')
IF item THEN unit := Val(item)
FreeDiskObject(dobj)
ENDIF
CurrentDir(olddir)
ELSE
-> Started from CLI
rargs := ReadArgs(TEMPLATE, arg_ptrs, NIL)
IF ARG_DEVICE THEN device := ARG_DEVICE
IF ARG_UNIT THEN unit := Long(ARG_UNIT)
ENDIF
-> No options?
IF (ARG_GENERATE=0) AND (ARG_MOUNT=0) AND (ARG_LIST=0)
PrintF(VERSION+6)
PrintF('Type: ''MountDos ?'' for an option summary.\n')
Raise(0)
ENDIF
-> Redirect output if option quiet is specified
IF (ARG_QUIET = TRUE)
conout := stdout := Open('NIL:', MODE_NEWFILE)
ENDIF
-> Trackdisk initialisation
tmp := CreateMsgPort()
tio := CreateIORequest(tmp, SIZEOF ioexttd)
OpenDevice(device, unit, tio, 0)
topen := TRUE
-> Actions to perform <-
IF ARG_LIST
list_table()
ENDIF
IF ARG_GENERATE
dosparts := ndosparts := 0
generate()
ENDIF
IF ARG_MOUNT
mount()
ENDIF
EXCEPT DO
/* Inspect the error (if any) */
IF exception <> 0
rc := RETURN_FAIL
SELECT exception
CASE "DEV"
PrintF('Unable to open device ''\s'', unit \d.\n', device, unit)
CASE "DOS"
PrintFault(IoErr(), NIL)
CASE "CTLC"
PrintF('Ctrl-C detected.\n')
CASE "IO"
PrintF('Device IO-error $\h.\n', tio.iostd.error)
CASE "LIB"
PrintF('Unable to open a needed library.\n')
CASE "MEM"
PrintF('Unable to allocate memory.\n')
CASE "RES"
PrintF('Unable to allocate needed resources.\n')
CASE "STAC"
PrintF('Stack overflow.\n')
DEFAULT
PrintF('Unknown exception: $\h.\n', exception)
ENDSELECT
ENDIF
/* Clean-up */
IF topen THEN CloseDevice (tio)
IF tio THEN DeleteIORequest(tio)
IF tmp THEN DeleteMsgPort (tmp)
IF iconbase THEN CloseLibrary (iconbase)
IF rargs THEN FreeArgs (rargs)
ENDPROC rc
/************ Read a partition-table block from disk *************/
PROC readblock(buffer, block)
tio.iostd.command := CMD_READ
tio.iostd.data := buffer
tio.iostd.length := SECTOR_SIZE
tio.iostd.offset := Mul(block,SECTOR_SIZE)
tio.iostd.flags := IOF_QUICK
DoIO(tio)
-> Check table ID
IF Int(buffer + $01FE) <> PART_TABLE_FLAG
PrintF('WARNING: Invalid tabel flag $\z\h[4].\n', Int(buffer + $01FE))
rc := RETURN_WARN
ENDIF
ENDPROC
/************ Auto-mount dos-partitions ************
* Generate the mountlist-entries in a file and call the mount
* command to mount each dos-partition in it.
*/
PROC mount() HANDLE
DEF cnt, tmp, tmpname
DEF command[80] :STRING
tmpname := TMPFILENAME -> Only one instance of string in object-code
tmp := stdout -> Temperary redirected.
stdout := Open(tmpname, MODE_NEWFILE)
IF stdout=NIL
stdout := tmp
PrintF('Unable to create a temporary mountlist.\n')
rc := RETURN_ERROR
RETURN
ENDIF
dosparts := ndosparts := 0
generate(0, TRUE)
Close(stdout)
stdout := tmp -> Restored
FOR cnt := 1 TO dosparts STEP 1
CtrlC() -> User may want to cancel the mount-procedure
PrintF('Mounting MD\d\d:\n', unit, cnt)
StringF(command,'Mount MD\d\d: FROM \s', unit, cnt, tmpname)
tmp := SystemTagList(command, [SYS_OUTPUT, stdout, TAG_DONE])
IF tmp > rc THEN rc := tmp -> Copy highest return-code
ENDFOR
EXCEPT DO
DeleteFile(tmpname)
ReThrow()
ENDPROC
/************ Generate mountlist-entries for partition chain ************/
-> 'dosonly' indicates only dos-partitions should be generated.
PROC generate(block=0, dosonly=FALSE)
DEF cnt, bpt, lowcyl, highcyl, isdos
-> Partition table
DEF buffer[SECTOR_SIZE] : ARRAY OF CHAR
DEF p:PTR TO partition -> Pointer to the partition table
-> Recursive function, check Ctrl-C and stack (uses auto-exceptions).
FreeStack()
CtrlC()
-> Read partition-table block
readblock(buffer, block)
p := buffer + $01BE
FOR cnt := 1 TO 4 STEP 1
-> Swap 'Intel'-values:
p.start_sect := swapL(p.start_sect)
p.nr_sects := swapL(p.nr_sects)
-> Can this partition be mounted with CrossDos or not?
IF (p.sys_ind=1) OR (p.sys_ind=4) OR (p.sys_ind=6)
INC dosparts
isdos := TRUE
ELSE
INC ndosparts
isdos := FALSE
ENDIF
IF (p.sys_ind <> 0) AND (p.sys_ind <> EXTENDED) AND
( (dosonly AND isdos) OR Not(dosonly) )
lowcyl := p.start_sect + block
highcyl := lowcyl + p.nr_sects + block
lowcyl, highcyl, bpt := smaller(lowcyl, highcyl)
PrintF(
'\s\d\d:\n'+
'FileSystem = \s\n'+
'Device = \s\n'+
'Unit = \d\n'+
'Surfaces = 1\n'+
'BlocksPerTrack = \d\n'+
'Reserved = 0\n'+
'LowCyl = \d\n'+
'HighCyl = \d\n'+
'BufMemType = 0\n'+
'Priority = 10\n'+
'GlobVec = -1\n'+
'DosType = \s\n'+
'Activate = 1\n'+
'#\n\n',
IF isdos THEN 'MD' ELSE 'ND', unit,
IF isdos THEN dosparts ELSE ndosparts,
IF isdos THEN 'L:CrossDOSFileSystem' ELSE systype(p.sys_ind),
device, unit, bpt, lowcyl, highcyl - 1,
IF isdos THEN '0x4D534400' ELSE '?',
)
ENDIF
IF (p.sys_ind = EXTENDED) AND (p.start_sect <> 0)
generate(p.start_sect + block, dosonly)
ENDIF
p++
ENDFOR
ENDPROC
/************ Shows the contents of an partition chain. ************/
PROC list_table(block=0)
DEF cnt
-> Partition table
DEF buffer[SECTOR_SIZE] : ARRAY OF CHAR
DEF p:PTR TO partition -> Pointer to the partition table
-> Recursive function, check Ctrl-C and stack (uses auto-exceptions).
FreeStack()
CtrlC()
-> Read partition-table block
readblock(buffer, block)
p := buffer + $01BE
PrintF(' Start: End: Start Number of\n'+
' boot Head Cyl. Sect Head Cyl. Sect Sector Sectors MB System\n')
FOR cnt := 1 TO 4 STEP 1
-> Swap 'Intel'-values:
p.start_sect := swapL(p.start_sect)
p.nr_sects := swapL(p.nr_sects)
PrintF('\d[1] \s \d[4]\d[5]\d[5] \d[4]\d[5]\d[5] \d[8] \d[9] \d[4] \s\n',
cnt, IF (p.boot_ind) THEN 'yes' ELSE 'no ',
p.head, CYLINDER(p.sector, p.cyl), SECTOR(p.sector),
p.end_head, CYLINDER(p.end_sector, p.end_cyl), SECTOR(p.end_sector),
IF p.start_sect = 0 THEN 0 ELSE p.start_sect + block, p.nr_sects,
p.nr_sects / ($100000/SECTOR_SIZE), systype(p.sys_ind)
)
p++
ENDFOR
-> Check for extended partitions.
p := buffer + $01BE
FOR cnt := 1 TO 4 STEP 1
IF p.sys_ind = EXTENDED
IF p.start_sect = 0
PrintF('Bad offset in extended partition number \d.\n', cnt)
ELSE
-> Recursive call of this funtion.
PrintF('\nExtended partition at sector \d:\n', p.start_sect + block)
list_table(p.start_sect + block)
ENDIF
ENDIF
p++
ENDFOR
ENDPROC
/********** System types of partitions *****************/
PROC systype(t)
DEF stypes: PTR TO LONG
stypes := [
0, 'Empty',
1, 'DOS 12-bit FAT',
2, 'XENIX root',
3, 'XENIX usr',
4, 'DOS 16-bit <32M',
EXTENDED, 'Extended',
6, 'DOS 16-bit >=32M',
7, 'OS/2 HPFS', -> or QNX?
8, 'AIX',
9, 'AIX bootable',
10, 'OPUS',
$40, 'Venix 80286',
$51, 'Novell?',
$52, 'Microport', -> or CPM?
$63, 'GNU HURD', -> or System V/386?
$64, 'Novell',
$75, 'PC/IX',
$80, 'Old MINIX', -> Minix 1.4a and earlier
$81, 'Linux/MINIX', -> Minix 1.4b and later
$82, 'Linux swap',
$83, 'Linux native',
$93, 'Amoeba',
$94, 'Amoeba BBT', -> (bad block table)
$b7, 'BSDI fs',
$b8, 'BSDI swap',
$c7, 'Syrinx',
$db, 'CP/M', -> or Concurrent DOS?
$e1, 'DOS access',
$e3, 'DOS R/O',
$f2, 'DOS secondary',
$ff, 'BBT' -> (bad track table)
]
WHILE (t <= $FF) AND (t > stypes[])
stypes++
stypes++
ENDWHILE
ENDPROC IF (t = stypes[]) THEN stypes[1] ELSE 'Unknown'
/*** Some assembler routines for convenience... ***/
/******** Lower the values of lowcyl and highcyl. ********
* Some file-systems/devices can't handle high values for the cylinders
* (probably higher than 65536). So we try to keep them low, by increasing
* the number of cylinders.
*/
PROC smaller(lowcyl, highcyl)
DEF bpt
MOVE.L lowcyl,D0
MOVE.L highcyl,D1
MOVEQ.L #1,D2 -> Sectors per track.
smaller_itterate:
BTST #0,D0
BNE smaller_end
BTST #0,D1
BNE smaller_end
LSL.W #1,D2
LSR.L #1,D0
LSR.L #1,D1
CMP.W #$0800,D2 -> Don't overreact (or hang).
BLT smaller_itterate
smaller_end:
MOVE.L D0,lowcyl
MOVE.L D1,highcyl
MOVE.L D2,bpt
ENDPROC lowcyl, highcyl, bpt
/****** Swap nibbles. Stupid Intel things... *********/
PROC swapL(l)
MOVE.L l,D0
ROR.W #8,D0
SWAP.W D0
ROR.W #8,D0
ENDPROC D0